#include "vlgameelementscontextwidget.h"

VLGameElementsContextWidget::VLGameElementsContextWidget(QWidget *parent) :
    VLContextWidget(parent)
{
    layout = setupLayout();

    nameLabel = createAndAddLabel(layout, tr("GAME ELEMENTS"));

    widgets = new QMap<GAME_ELEMENT_TYPE, QList<QWidget *> >();

    setupElements();
    setupDoorSubContext();
    setupEnemyContext();
    setupSpikesContext();
    setupLadderContext();
    setupSwitchContext();
    setDefaults();
}

VLGameElementsContextWidget*
VLGameElementsContextWidget::getInstance(){
    static VLGameElementsContextWidget* inst=0;
    if(!inst)return inst = new VLGameElementsContextWidget();
    else return inst;
}

void VLGameElementsContextWidget::setDefaults() {
    currentElement = DOOR;
    showWidgets(widgets->value(currentElement));
}

void VLGameElementsContextWidget::setupElements() {
    elementsOptions = new QStringList();
    *elementsOptions << tr("Door") << tr("Enemy") << tr("Spikes") << tr("Ladder") << tr("Switch");
    elementsBox = createAndAddComboBox(layout, elementsOptions);

    elementsLabel = createAndAddLabel(layout, tr("(None)"));

    connect(elementsBox, SIGNAL(activated(int)), this, SLOT(setCurrentElement(int)));
}

void VLGameElementsContextWidget::setupDoorSubContext() {
    QLabel *faceSide = createAndAddLabel(layout, tr("Face side:"));
    doorOptions = new QStringList();
    *doorOptions << "Front" << "Side";
    doorFaceSideBox = createAndAddComboBox(layout, doorOptions);
    connect(doorFaceSideBox, SIGNAL(activated(int)), this, SLOT(setDoorFaceSide(int)));

    QList<QWidget *> *l = new QList<QWidget *>();
    l->append(faceSide);
    l->append(doorFaceSideBox);
    widgets->insert(DOOR, *l);
    hideWidgets(*l);
}

void VLGameElementsContextWidget::setupEnemyContext() {
    QList<QWidget *> *l = new QList<QWidget *>();
    QLabel *speedLabel = createAndAddLabel(layout, tr("Speed:"));
    l->append(speedLabel);
    enemySpeedBox = createAndAddSpinBox(layout, 0, 100);
    connect(enemySpeedBox, SIGNAL(valueChanged(int)), this, SLOT(setEnemySpeed(int)));
    l->append(enemySpeedBox);
    QLabel *detRangeLabel = createAndAddLabel(layout, tr("Detection Range (WxD):"));
    l->append(detRangeLabel);
    enemyWidth = createAndAddSpinBox(layout, 0, 100);
    enemyWidth->setButtonSymbols(QAbstractSpinBox::NoButtons);
    connect(enemyWidth, SIGNAL(valueChanged(int)), this, SLOT(setEnemyWidth(int)));
    l->append(enemyWidth);
    enemySpacer = createAndAddLabel(layout, tr("x"));
    l->append(enemySpacer);
    enemyDepth = createAndAddSpinBox(layout, 0, 100);
    enemyDepth->setButtonSymbols(QAbstractSpinBox::NoButtons);
    connect(enemyDepth, SIGNAL(valueChanged(int)), this, SLOT(setEnemyDepth(int)));
    l->append(enemyDepth);
    widgets->insert(ENEMY, *l);
    hideWidgets(*l);
}

void VLGameElementsContextWidget::setupSpikesContext() {
    QList<QWidget *> *l = new QList<QWidget *>();
    QLabel *damageLabel = createAndAddLabel(layout, tr("Damage"));
    l->append(damageLabel);
    spikesDamageBox = createAndAddSpinBox(layout, 0, 100);
    connect(spikesDamageBox, SIGNAL(valueChanged(int)), this, SLOT(setSpikesDamage(int)));
    l->append(spikesDamageBox);
    widgets->insert(SPIKES, *l);
    hideWidgets(*l);
}

void VLGameElementsContextWidget::setupLadderContext() {
    QList<QWidget *> *l = new QList<QWidget *>();
    QLabel *orientLabel = createAndAddLabel(layout, tr("Orientation:"));
    l->append(orientLabel);
    ladderOrientations = new QStringList();
    *ladderOrientations << tr("FRONT") << tr("RIGHT") << tr("BACK") << tr("LEFT");
    ladderOrientationBox = createAndAddComboBox(layout, ladderOrientations);
    connect(ladderOrientationBox, SIGNAL(activated(int)), this, SLOT(setLadderOrientation(int)));
    l->append(ladderOrientationBox);
    widgets->insert(LADDER, *l);
    hideWidgets(*l);
}

void VLGameElementsContextWidget::setupSwitchContext() {
    QList<QWidget *> *l = new QList<QWidget *>();

    QLabel *targetsLabel = createAndAddLabel(layout, tr("Targets:"));
    l->append(targetsLabel);
    switchTargets = new QStringList();
    switchTargetsBox = createAndAddComboBox(layout, switchTargets);
    switchTargetsBox->setSizeAdjustPolicy(QComboBox::AdjustToContents);

    switchTargetRemove = createAndAddButton(layout,"Remove");
    connect(switchTargetRemove, SIGNAL(clicked()), this, SLOT(removeSwitchTarget()));

    l->append(switchTargetsBox);
    l->append(switchTargetRemove);
    widgets->insert(SWITCH, *l);
    hideWidgets(*l);
}

void VLGameElementsContextWidget::setCurrentElement(int elem) {
    if(((GAME_ELEMENT_TYPE)elem)==NO_TYPE)return;
    printf("element: %d\n",elem);
    hideWidgets(widgets->value(currentElement));
    showWidgets(widgets->value((GAME_ELEMENT_TYPE) elem));
    currentElement = (GAME_ELEMENT_TYPE) elem;
}

void VLGameElementsContextWidget::updateGUIElement(int elem){
    if(((GAME_ELEMENT_TYPE)elem)==NO_TYPE)return;
    setCurrentElement(elem);

    //if(TOOL_GAME_ELEMENT->getCurrentGenericElement())
    switch((GAME_ELEMENT_TYPE)elem)
    {
        case DOOR:
        if(ElementDoor* e=TOOL_GAME_ELEMENT->getCurrentElement<ElementDoor,DOOR>())
        {
            doorFaceSideBox->setCurrentIndex(e->getFaceSide());
        }
        break;

        case ENEMY:
        if(ElementEnemy* e=TOOL_GAME_ELEMENT->getCurrentElement<ElementEnemy,ENEMY>())
        {
            enemySpeedBox->setValue(e->getSpeed());
            enemyWidth->setValue(e->getDetectionWidth());
            enemyDepth->setValue(e->getDetectionDepth());
        }
        break;

        case SWITCH:
        if(ElementSwitch* e=TOOL_GAME_ELEMENT->getCurrentElement<ElementSwitch,SWITCH>())
        {
            updateSwitchTargetList(e);
        }
        break;

        case SPIKES:
        if(ElementSpikes* e=TOOL_GAME_ELEMENT->getCurrentElement<ElementSpikes,SPIKES>())
        {
            spikesDamageBox->setValue(e->getDamage());
        }
        break;

        case LADDER:
        if(ElementLadder* e=TOOL_GAME_ELEMENT->getCurrentElement<ElementLadder,LADDER>())
        {
            ladderOrientationBox->setCurrentIndex(e->getOrientation());
        }
        break;

        default:
        break;
    }

    makeName(TOOL_GAME_ELEMENT->getCurrentGenericElement());
    elementsLabel->setText(nameBuf);
    updateComboBox(elem);
}

void VLGameElementsContextWidget::setDoorFaceSide(int index) {
    doorFaceSideBox->setCurrentIndex(index);
    emit doorFaceSideChanged(index);
}

void VLGameElementsContextWidget::setEnemySpeed(int val) {
    enemySpeedBox->setValue(val);
    emit enemySpeedChanged(val);
}

void VLGameElementsContextWidget::setEnemyWidth(int val) {
    enemyWidth->setValue(val);
    emit enemyWidthChanged(val);
}

void VLGameElementsContextWidget::setEnemyDepth(int val) {
    enemyDepth->setValue(val);
    emit enemyDepthChanged(val);
}

void VLGameElementsContextWidget::setSpikesDamage(int val) {
    spikesDamageBox->setValue(val);
    emit spikesDamageChanged(val);
}

void VLGameElementsContextWidget::setLadderOrientation(int index) {
    ladderOrientationBox->setCurrentIndex(index);
    emit ladderOrientationChanged(index);
}

void VLGameElementsContextWidget::removeSwitchTarget()
{
    if(ElementSwitch* e=TOOL_GAME_ELEMENT->getCurrentElement<ElementSwitch,SWITCH>())
    {
        e->removeTarget(switchTargetsBox->currentIndex());
        updateSwitchTargetList(e);
    }
}

void VLGameElementsContextWidget::updateComboBox(int index){
    elementsBox->setCurrentIndex(index);
}

void VLGameElementsContextWidget::hideWidgets(QList<QWidget *> visibleWidgets) {
    for (int i = 0; i < visibleWidgets.size(); i++) {
        visibleWidgets.at(i)->setVisible(false);
    }
}

void VLGameElementsContextWidget::showWidgets(QList<QWidget *> hiddenWidgets) {
    for (int i = 0; i < hiddenWidgets.size(); i++) {
        hiddenWidgets.at(i)->setVisible(true);
    }
}

void VLGameElementsContextWidget::updateSwitchTargetList(ElementSwitch *e){
    switchTargetsBox->clear();
    SWITCH_TARGET_ARRAY& arr = e->getTargets();

    for(int i=0;i<arr.size();i++)
    {
        makeName(arr[i]);
        switchTargetsBox->addItem(nameBuf);
    }
}

void VLGameElementsContextWidget::makeName(GameElement* e)
{
    if(e){
        const char* name = e->getName();
        vector3<int> pos = e->s.position.cast<int>();
        strncpy(nameBuf,name,MAX_BUF_SIZE);
        sprintf(nameBuf+strlen(name),"(%d, %d, %d)",pos.x,pos.y,pos.z);
    }
    else strncpy(nameBuf,"(None)",MAX_BUF_SIZE);
}

int VLGameElementsContextWidget::getSwitchCurrentTarget()
{
    return switchTargetsBox->currentIndex();
}
